﻿#include "ssNodeFactory.h"
#include "../shader/ssShaderManager.h"
#include "../element/camera/ssThirdPersonCamera.h"
#include "../element/material/ssTextureMaterial.h"
#include "../element/material/ssBillboardMaterial.h"
#include "../element/material/ssLightMaterial.h"
#include "../element/material/ssTerrain10Material.h"
#include "../element/render/ssAxesRender.h"
#include "../element/render/ssLineRender.h"
#include "../element/render/ssTerrain10Render.h"
#include "../resmgr/ssResManager.h"


namespace StarSeeker
{

ssNodeFactory::ssNodeFactory()
{
}

ssNodeFactory::~ssNodeFactory()
{
}

ssNode* ssNodeFactory::CreateCamera()
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Camera");
	ssCamera* cam = new ssCamera();
	pNode->AddComponent(cam);
	return pNode;
}

ssNode* ssNodeFactory::CreateThirdPersonCamera()
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Camera");
	ssThirdPersonCamera* cam = new ssThirdPersonCamera();
	pNode->AddComponent(cam);
	return pNode;
}

ssNode* ssNodeFactory::CreateAxesNode(ssfloat axesLength)
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Axes");
	StarSeeker::ssAxesRender* pRender = new StarSeeker::ssAxesRender();
	StarSeeker::ssMaterial* pMaterial = new StarSeeker::ssMaterial();
	pRender->CreateAxes(axesLength);
	StarSeeker::ssShader* pAxesShader = StarSeeker::ssShaderManager::instance()->Find("color");
	pMaterial->SetShader(pAxesShader);
	pNode->AddComponent(pRender);
	pNode->AddComponent(pMaterial);
	return pNode;
}

ssNode* ssNodeFactory::CreateBoardNode(ssTexture2D* pTexture, ssfloat width, ssfloat height)
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Board");
	StarSeeker::ssTextureMaterial* pMaterial = new StarSeeker::ssTextureMaterial();
	if (pTexture) pMaterial->SetTexture(pTexture);
	StarSeeker::ssShader* pTextureShader = StarSeeker::ssShaderManager::instance()->Find("texture2d");
	pMaterial->SetShader(pTextureShader);
	StarSeeker::ssTexture2dRender* pRender = new StarSeeker::ssTexture2dRender();
	pRender->SetVDF(SS_ES_ALPHA);
	pRender->SetDataFromMesh(1, "panel");
	pNode->AddComponent(pMaterial);
	pNode->AddComponent(pRender);
	pNode->Transform().SetScaling(width, 1.0f, height);
	return pNode;
}

ssNode* ssNodeFactory::CreateBoardNode(const char* texturePath, ssfloat width /*= 128.0f*/, ssfloat height /*= 128.0f*/)
{
	ssError ret = SS_RES_MANAGR->LoadPicture(texturePath);
	if (ret==SS_OK || ret==SS_LOADRES_EXISTS)
	{
		StarSeeker::ssTexture2D* pTexture = new StarSeeker::ssTexture2D;
		pTexture->Load(texturePath);
		return CreateBoardNode(pTexture, width, height);
	}
	return 0;
}

ssNode* ssNodeFactory::CreateBillboardNode(ssTexture2D* pTexture, ssfloat width)
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Billboard");
	StarSeeker::ssBillboardMaterial* pMaterial = new StarSeeker::ssBillboardMaterial();
	if (pTexture) pMaterial->SetTexture(pTexture);
	StarSeeker::ssShader* pTextureShader = StarSeeker::ssShaderManager::instance()->Find("texture2d");
	pMaterial->SetShader(pTextureShader);
	StarSeeker::ssTexture2dRender* pRender = new StarSeeker::ssTexture2dRender();
	pRender->SetVDF(SS_ES_ALPHA);
	pRender->SetDataFromMesh(1, "quad");
	pNode->AddComponent(pMaterial);
	pNode->AddComponent(pRender);
	pNode->Transform().SetScaling(width, width, width);
	return pNode;
}

ssNode* ssNodeFactory::CreateBillboardNode(const char* texturePath, ssfloat width)
{
	ssError ret = SS_RES_MANAGR->LoadPicture(texturePath);
	if (ret == SS_OK || ret == SS_LOADRES_EXISTS)
	{
		StarSeeker::ssTexture2D* pTexture = new StarSeeker::ssTexture2D;
		pTexture->Load(texturePath);
		return CreateBillboardNode(pTexture, width);
	}
	return 0;
}

StarSeeker::ssNode* ssNodeFactory::CreateModelNode(const char* modelPath)
{
	ssError ret = SS_RES_MANAGR->LoadMesh(modelPath);
	if (ret == SS_OK || ret == SS_LOADRES_EXISTS)
	{
		StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Model");
		StarSeeker::ssMaterial* pMaterial = new StarSeeker::ssMaterial();
		StarSeeker::ssShader* pShader = StarSeeker::ssShaderManager::instance()->Find("base");
		pMaterial->SetShader(pShader);
		StarSeeker::ssMeshRender* pModRender = new StarSeeker::ssMeshRender();
		pModRender->SetDataFromMesh(modelPath);
		pNode->AddComponent(pMaterial);
		pNode->AddComponent(pModRender);
		return pNode;
	}
	return 0;
}

ssNode * ssNodeFactory::CreateBoxNode()
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("box");
	StarSeeker::ssMaterial* pMaterial = new StarSeeker::ssMaterial();
	StarSeeker::ssShader* pShader = StarSeeker::ssShaderManager::instance()->Find("base");
	pMaterial->SetShader(pShader);
	StarSeeker::ssMeshRender* pRender = new StarSeeker::ssMeshRender();
	pRender->SetDataFromMesh("box");
	pNode->AddComponent(pMaterial);
	pNode->AddComponent(pRender);
	return pNode;
}

ssNode * ssNodeFactory::CreateDiamondNode()
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("diamond");
	StarSeeker::ssMaterial* pMaterial = new StarSeeker::ssMaterial();
	StarSeeker::ssShader* pShader = StarSeeker::ssShaderManager::instance()->Find("base");
	pMaterial->SetShader(pShader);
	StarSeeker::ssMeshRender* pRender = new StarSeeker::ssMeshRender();
	pRender->SetDataFromMesh("diamond");
	pNode->AddComponent(pMaterial);
	pNode->AddComponent(pRender);
	return pNode;
}

ssNode* ssNodeFactory::CreateTextureModelNode(ssTexture2D* pTexture, const char* modelPath)
{
	ssError ret = SS_RES_MANAGR->LoadMesh(modelPath);
	if (ret == SS_OK || ret == SS_LOADRES_EXISTS)
	{
		StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Model");
		StarSeeker::ssTextureMaterial* pMaterial = new StarSeeker::ssTextureMaterial();
		if (pTexture) pMaterial->SetTexture(pTexture);
		StarSeeker::ssShader* pShader = StarSeeker::ssShaderManager::instance()->Find("texture2d");
		pMaterial->SetShader(pShader);
		StarSeeker::ssTexture2dRender* pModRender = new StarSeeker::ssTexture2dRender();
		pModRender->SetDataFromMesh(1, modelPath);
		pNode->AddComponent(pMaterial);
		pNode->AddComponent(pModRender);
		return pNode;
	}
	return 0;
}

ssNode* ssNodeFactory::CreateTextureModelNode(const char* texturePath, const char* modelPath)
{
	ssError ret = SS_RES_MANAGR->LoadPicture(texturePath);
	if (ret == SS_OK || ret == SS_LOADRES_EXISTS)
	{
		StarSeeker::ssTexture2D* pTextureMd = new StarSeeker::ssTexture2D;
		pTextureMd->Load(texturePath);

		return CreateTextureModelNode(pTextureMd, modelPath);
	}
	return 0;
}

ssNode* ssNodeFactory::CreateLightTextureModelNode(ssTexture2D* pTexture, const char* modelPath)
{
	ssError ret = SS_RES_MANAGR->LoadMesh(modelPath);
	if (ret == SS_OK || ret == SS_LOADRES_EXISTS)
	{
		StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Model");
		StarSeeker::ssLightMaterial* pMaterial = new StarSeeker::ssLightMaterial();
		if (pTexture) pMaterial->SetTexture(pTexture);
		StarSeeker::ssShader* pShader = StarSeeker::ssShaderManager::instance()->Find("vlightingTex");
		pMaterial->SetShader(pShader);
		StarSeeker::ssTexture2dRender* pModRender = new StarSeeker::ssTexture2dRender();
		pModRender->SetDataFromMesh(1, modelPath);
		pNode->AddComponent(pMaterial);
		pNode->AddComponent(pModRender);
		return pNode;
	}
	return 0;
}

ssNode* ssNodeFactory::CreateLightTextureModelNode(const char* texturePath, const char* modelPath)
{
	ssError ret = SS_RES_MANAGR->LoadPicture(texturePath);
	if (ret == SS_OK || ret == SS_LOADRES_EXISTS)
	{
		StarSeeker::ssTexture2D* pTextureMd = new StarSeeker::ssTexture2D;
		pTextureMd->Load(texturePath);

		return CreateLightTextureModelNode(pTextureMd, modelPath);
	}
	return 0;
}

ssNode* ssNodeFactory::CreatePixelLightTextureModelNode(ssTexture2D* pTexture, const char* modelPath)
{
	ssError ret = SS_RES_MANAGR->LoadMesh(modelPath);
	if (ret == SS_OK || ret == SS_LOADRES_EXISTS)
	{
		StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Model");
		StarSeeker::ssLightMaterial* pMaterial = new StarSeeker::ssLightMaterial();
		if (pTexture) pMaterial->SetTexture(pTexture);
		StarSeeker::ssShader* pShader = StarSeeker::ssShaderManager::instance()->Find("plighting");
		pMaterial->SetShader(pShader);
		StarSeeker::ssTexture2dRender* pModRender = new StarSeeker::ssTexture2dRender();
		pModRender->SetDataFromMesh(1, modelPath);
		pNode->AddComponent(pMaterial);
		pNode->AddComponent(pModRender);
		return pNode;
	}
	return 0;
}

ssNode * ssNodeFactory::CreatePixelLightTextureModelNode(const char * texturePath, const char* normalTexturePath, const char * modelPath)
{
	SS_RES_MANAGR->LoadPicture(texturePath);
	SS_RES_MANAGR->LoadPicture(normalTexturePath);
	StarSeeker::ssTexture2D* pTextureMd = new StarSeeker::ssTexture2D;
	pTextureMd->Load(texturePath);
	pTextureMd->Load(normalTexturePath);
	return CreatePixelLightTextureModelNode(pTextureMd, modelPath);
}

StarSeeker::ssNode* ssNodeFactory::CreateLineNode(ssfloat x1, ssfloat y1, ssfloat z1, ssfloat x2, ssfloat y2, ssfloat z2, ssfloat r, ssfloat g, ssfloat b, ssfloat a)
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Line");
	StarSeeker::ssLineRender* pRender = new StarSeeker::ssLineRender();
	StarSeeker::ssMaterial* pMaterial = new StarSeeker::ssMaterial();
	pRender->CreateLine(x1, y1, z1, x2, y2, z2, r, g, b, a);
	StarSeeker::ssShader* pAxesShader = StarSeeker::ssShaderManager::instance()->Find("color");
	pMaterial->SetShader(pAxesShader);
	pNode->AddComponent(pRender);
	pNode->AddComponent(pMaterial);
	return pNode;
}

StarSeeker::ssNode* ssNodeFactory::CreateLineNode(ssVector3 p1, ssVector3 p2, ssColor4 c)
{
	return CreateLineNode(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, c.r, c.g, c.b, c.a);
}

StarSeeker::ssNode* ssNodeFactory::CreateTerrain10Node(ssTexture2D* pTexture)
{
	StarSeeker::ssNode* pNode = new StarSeeker::ssNode("Terrain1.0");
	StarSeeker::ssTerrain10Material* pMaterial = new StarSeeker::ssTerrain10Material();
	if (pTexture) pMaterial->SetTexture(pTexture);
	StarSeeker::ssShader* pShader = StarSeeker::ssShaderManager::instance()->Find("terrain1.0");
	pMaterial->Init(pShader, 0.f, 100.f, 100.f*100.f, 100.f*100.f);
	StarSeeker::ssTerrain10Render* pTerrainRender = new StarSeeker::ssTerrain10Render();
	pTerrainRender->BuildGrid(100, 100, 100.f);
	pNode->AddComponent(pMaterial);
	pNode->AddComponent(pTerrainRender);
	return pNode;
}

StarSeeker::ssNode* ssNodeFactory::CreateTerrain10Node(const char* hightPath, const char* texturePath1, const char* texturePath2)
{
	SS_RES_MANAGR->LoadPicture(hightPath);
	SS_RES_MANAGR->LoadPicture(texturePath1);
	SS_RES_MANAGR->LoadPicture(texturePath2);
	StarSeeker::ssTexture2D* pTextureMd = new StarSeeker::ssTexture2D;
	pTextureMd->Load(hightPath);
	pTextureMd->Load(texturePath1);
	pTextureMd->Load(texturePath2);
	return CreateTerrain10Node(pTextureMd);
}

}
